home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Cafe 3
/
Visual Cafe 3.ISO
/
Vcafe
/
JFC.bin
/
MacTextUI.java
< prev
next >
Wrap
Text File
|
1998-06-30
|
16KB
|
527 lines
/*
* @(#)MacTextUI.java 1.7 98/02/02
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing.plaf.mac;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import com.sun.java.swing.text.*;
import com.sun.java.swing.plaf.*;
import com.sun.java.swing.border.Border;
/**
* <p>
* Warning: serialized objects of this class will not be compatible with
* future swing releases. The current serialization support is appropriate
* for short term storage or RMI between Swing1.0 applications. It will
* not be possible to load serialized Swing1.0 objects with future releases
* of Swing. The JDK1.2 release of Swing will be the compatibility
* baseline for the serialized form of Swing objects.
*
* @version 1.7 02/02/98
* @author Symantec
*/
public abstract class MacTextUI extends DefaultTextUI {
Window parentWindow = null;
MacTextAncestorListener anAncestorListener;
boolean activated = false;
//set border and
//install Ancestor Listener
protected void installDefaults(JComponent c)
{
JTextComponent editor = getComponent();
editor.setBorder(MacBorderFactory.getTextBorder());
//set up listener so we know when addNotify and removeNotify are called
anAncestorListener = new MacTextAncestorListener();
editor.addAncestorListener(anAncestorListener);
//load these here so I can switch foreground color if needed
String prefix = getPropertyPrefix();
Color sbg = editor.getSelectionColor();
if ((sbg == null) || (sbg instanceof UIResource)) {
editor.setSelectionColor(UIManager.getColor(prefix + ".selectionBackground"));
}
Color sfg = editor.getSelectedTextColor();
if ((sfg == null) || (sfg instanceof UIResource)) {
editor.setSelectedTextColor(UIManager.getColor(prefix + ".selectionForeground"));
}
//if both black, switch text color to white
// if(sbg.equals(Color.black) && (sfg.equals(Color.black)))
// editor.setSelectedTextColor(MacUtilities.GrayscaleAppearanceW);
super.installDefaults(c);
}
//remove Ancestor Listener
protected void uninstallDefaults(JComponent c)
{
JTextComponent editor = getComponent();
editor.removeAncestorListener(anAncestorListener);
super.uninstallDefaults(c);
}
public JTextComponent getComponentEditor()
{
return getComponent();
}
/**
* return true if point in non-border area
*
* @param c the editor component
* @param x the horizontal coordinate
* @param y the vertical coordinate
*/
public boolean contains(JComponent c, int x, int y)
{
Rectangle viewRect = new Rectangle(c.getSize());
Insets i = c.getInsets();
viewRect.x += i.left;
viewRect.y += i.top;
viewRect.width -= (i.right + viewRect.x);
viewRect.height -= (i.bottom + viewRect.y);
return viewRect.contains(x, y);
}
/**
* Override so that if opaque the edges are painted
* in parent's background color.
* Interior is painted in component's background color
* in paintBackground.
* @see paintBackground
*
* @param g the graphics context
* @param c the editor component
*/
public void update(Graphics g, JComponent c)
{
Rectangle viewRect = new Rectangle(c.getSize());
Insets i = c.getInsets();
if (c.isOpaque()) {
//if there is an inset, draw the correct frame
if(i.left > 0) {
g.setColor(c.getParent().getBackground());
int h = c.getHeight();
int w = c.getWidth();
//if not in focus, draw where focus border would be
if(!c.hasFocus()) {
g.drawRect(0, 0, w - 1, h - 1);
g.drawRect(1, 1, w - 2, h - 2);
} else {//just draw corner pixels
g.drawLine(0, 0, 0, 0);
g.drawLine(0, h-1, 0, h-1);
g.drawLine(w-1, 0, w-1, 0);
g.drawLine(w-1, h-1, w-1, h-1);
}
}
}
//paint in background for interior
g.setColor(c.getBackground());
viewRect.x += i.left;
viewRect.y += i.top;
viewRect.width -= (i.right + viewRect.x);
viewRect.height -= (i.bottom + viewRect.y);
g.fillRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height);
paint(g, c);
}
/**
* Paint a background for the view. This will only be
* called if isOpaque() on the associated component is
* true. It does check for the insets of the border.
*
* @param g the graphics context
*/
protected void paintBackground(Graphics g)
{
JTextComponent editor = getComponentEditor();
g.setColor(editor.getBackground());
Rectangle viewRect = new Rectangle(editor.getSize());
Insets i = editor.getInsets();
viewRect.x += i.left;
viewRect.y += i.top;
viewRect.width -= (i.right + viewRect.x);
viewRect.height -= (i.bottom + viewRect.y);
g.fillRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height);
}
/**
* Load the given keymap with default settings
* appropriate for the UI being created. This
* is called if a default keymap is being created
* because an existing one wasn't found. Subclasses
* that reimplement this would generally want to
* call the superclass implementation to make sure
* all of the appropriate bindings get loaded.
*
* This is implemented to load the set of keybindings
* appropriate for all text components in mac.
*/
protected void loadDefaultKeymap(Keymap map) {
JTextComponent.loadKeymap(map, defaultBindings,
getComponent().getActions());
}
/**
* Allows one to fetch the name of the keymap that
* will be installed/used by default for this UI.
* This is implemented to generate a name based upon
* the getPropertyPrefix method, and will generally
* need not be redefined.
*/
public String getKeymapName() {
return "Mac" + getPropertyPrefix();
}
/**
* Creates the object to use for a caret. By default an
* instance of MacTextUI.MacCaret is created. This method
* can be redefined to provide something else that implements
* the Caret interface.
*
* @return the caret object
*/
protected Caret createCaret() {
return new MacCaret();
}
/**
* Creates the keymap to use for the text component, and installs
* any necessary bindings into it. By default, the keymap is
* shared between all instances of the associated text component.
* It has the name defined by the getKeymapName method.
*
* @see #getKeymapName
* @see com.sun.java.swing.text.JTextComponent
*/
protected Keymap createKeymap() {
String nm = getKeymapName();
Keymap map = JTextComponent.getKeymap(nm);
if (map == null) {
Keymap parent = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
map = JTextComponent.addKeymap(nm, parent);
loadDefaultKeymap(map);
}
return map;
}
public void setActivated(boolean activated)
{
this.activated = activated;
}
public boolean isActivated()
{
return activated;
}
/**
* The mac caret is rendered as an vertical line.
* <p>
* Warning: serialized objects of this class will not be compatible with
* future swing releases. The current serialization support is appropriate
* for short term storage or RMI between Swing1.0 applications. It will
* not be possible to load serialized Swing1.0 objects with future releases
* of Swing. The JDK1.2 release of Swing will be the compatibility
* baseline for the serialized form of Swing objects.
*/
public class MacCaret extends DefaultCaret implements UIResource {
int preSelectionBlinkRate = -1;
/**
* Damages the area surrounding the caret to cause
* it to be repainted. If paint() is reimplemented,
* this method should also be reimplemented.
*
* @param r the current location of the caret
* @see #paint
*/
protected void damage(Rectangle r) {
if (r != null) {
Component c = getComponent();
c.repaint(r.x - 1, r.y,
r.width + 2, r.height);
}
}
/**
* Renders the caret as a vertical line. If this is reimplemented
* the damage method should also be reimplemented as it assumes the
* shape of the caret is a vertical line.
*
* @param g the graphics context
* @see #damage
*/
public void paint(Graphics g)
{
JTextComponent c = getComponent();
//if there is a selection, don't blink
if(c.getSelectedText() != null)
{
if(preSelectionBlinkRate < 0)
{
preSelectionBlinkRate = getBlinkRate();
setBlinkRate(0);
}
return;
}
else //restore old blink rate and go on
{
if(preSelectionBlinkRate > 0)
{
setBlinkRate(preSelectionBlinkRate);
setVisible(true);
preSelectionBlinkRate = -1;
}
}
if(isVisible())
{
try
{
Color fg = isActivated() ? c.getCaretColor() :
c.getDisabledTextColor();
Color bg = c.getBackground();
if (fg.equals(bg))
g.setXORMode(bg); // Make sure caret is visible when the background color equals caret color
TextUI mapper = c.getUI();
int dot = getDot();
Rectangle r = mapper.modelToView(dot);
int x0 = r.x;
int y0 = r.y + 1;
int y1 = r.y + r.height - 2;
g.setColor(fg);
g.drawLine(x0, y0, x0, y1);
//enclosing window needs to be active for us to care
if((isActivated()) && (c.hasFocus() == false))
{
setVisible(false);
}
g.setPaintMode(); // reset back to normal mode
}
catch (BadLocationException e)
{
// can't render I guess
//System.err.println("Can't render caret");
}
}
}
/**
* Turns the caret on as a result of getting
* focus. The mac caret is visible when component has focus
* or when window is deactivated when component has focus
* but quits flashing when window is deactivated.
* Repaint entire component to paint focus rectangle
*/
public void focusGained(FocusEvent e) {
Caret caret = getComponent().getCaret();
if (lastBlinkRate >= 0) {
caret.setBlinkRate(lastBlinkRate);
}
caret.setVisible(true);
getComponent().repaint();
}
/**
* Turns the caret off as a result of losing
* focus. The mac caret is only visible
* when the component has focus, even if window is deactivated. The
* current blink rate is stashed so it can be
* restored later, and the rate is set to 0.
* The caret itself takes care of it's change
* in appearance.
* Repaint entire component to unpaint focus rectangle
*/
public void focusLost(FocusEvent e) {
Caret caret = getComponent().getCaret();
lastBlinkRate = caret.getBlinkRate();
caret.setBlinkRate(0);
caret.setDot(caret.getDot());
if(isActivated())
{
caret.setVisible(false);
}
else
{
caret.setVisible(true);
}
getComponent().getParent().repaint();
}
int lastBlinkRate = -1;
final int IBeamOverhang = 2;
}
class MacTextAncestorListener implements com.sun.java.swing.event.AncestorListener
{
TextWindowAdapter aTextWindowAdapter;
/**
* Called when the source or one of its ancestors is made visible
* either by setVisible(true) being called or by its being
* added to the component hierarchy. The method is only called
* if the source has actually become visible. For this to be true
* all its parents must be visible and it must be in a hierarchy
* rooted at a Window
*/
public void ancestorAdded(com.sun.java.swing.event.AncestorEvent event)
{
Component parent = null;
JTextComponent c = getComponentEditor();
int hHeight = 0, vWidth = 0;
Object object = event.getSource();
if(object == c )
parent = c.getParent();
while((parent != null) && (!(parent instanceof Window)))
parent = parent.getParent();
if(parent != null)
{
parentWindow = (Window)parent;
aTextWindowAdapter = new TextWindowAdapter();
parentWindow.addWindowListener(aTextWindowAdapter);
}
}
/**
* Called when the source or one of its ancestors is made invisible
* either by setVisible(false) being called or by its being
* remove from the component hierarchy. The method is only called
* if the source has actually become invisible. For this to be true
* at least one of its parents must by invisible or it is not in
* a hierarchy rooted at a Window
*/
public void ancestorRemoved(com.sun.java.swing.event.AncestorEvent event)
{
if(parentWindow != null)
parentWindow.removeWindowListener(aTextWindowAdapter);
}
/**
* Called when either the source or one of its ancestors is moved.
*/
public void ancestorMoved(com.sun.java.swing.event.AncestorEvent event)
{
}
}
class TextWindowAdapter extends java.awt.event.WindowAdapter
{
public void windowDeactivated(java.awt.event.WindowEvent event)
{
Object object = event.getSource();
if (object == parentWindow)
ParentWindow_WindowDeactivated(event);
}
public void windowActivated(java.awt.event.WindowEvent event)
{
Object object = event.getSource();
if (object == parentWindow)
ParentWindow_WindowActivated(event);
}
}
void ParentWindow_WindowActivated(java.awt.event.WindowEvent event)
{
setActivated(true);
//if it was active before, turn it on again
if(getComponent().getCaret().isVisible())
{
getComponent().requestFocus();
}
}
void ParentWindow_WindowDeactivated(java.awt.event.WindowEvent event)
{
setActivated(false);
}
/**
* Default bindings all keymaps implementing the Mac feel.
*/
static final JTextComponent.KeyBinding[] defaultBindings = {
new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT,
InputEvent.CTRL_MASK),
DefaultEditorKit.copyAction),
new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT,
InputEvent.SHIFT_MASK),
DefaultEditorKit.pasteAction),
new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE,
InputEvent.SHIFT_MASK),
DefaultEditorKit.cutAction),
new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,
InputEvent.SHIFT_MASK),
DefaultEditorKit.selectionBackwardAction),
new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,
InputEvent.SHIFT_MASK),
DefaultEditorKit.selectionForwardAction),
new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_F,
InputEvent.CTRL_MASK),
DefaultEditorKit.forwardAction),
new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_B,
InputEvent.CTRL_MASK),
DefaultEditorKit.backwardAction),
new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_D,
InputEvent.CTRL_MASK),
DefaultEditorKit.deleteNextCharAction),
};
}